﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GbmpClonedElementPostProcessor.h"
#include "IElementJoin.h"
#include "IJoinRelationshipBehavior.h"
#include "IElementOpening.h"
#include "IInstance.h"
#include "IOpeningRelationshipBehavior.h"
#include "IGeometryRelationshipComponent.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
using namespace std;

bool GbmpClonedElementPostProcessor::Do(IElement* pElement)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pElement, L"后处理对象为空",L"GDMPLab",L"2024-03-30");

    //如果是连接件(目前只做了调试)
    ProcessJoinableElement(pElement);

    //如果是连接本身
    ProcessJoinElement(pElement);

    //如果是被开洞对象
    ProcessOpenedOrOpeningElement(pElement);

    //如果是开洞本身
    ProcessOpenElement(pElement);

    return true;
}

bool GbmpClonedElementPostProcessor::ProcessJoinableElement(IElement* pElement)
{
    IDocument* pDoc = pElement->GetDocument();
    ElementId elementId = pElement->GetElementId();

    const IGeometryRelationshipComponent* pGeometryRepCpt = pElement->GetGeometryRelationshipComponent();
    if (pGeometryRepCpt == nullptr)
        return true;

    //如果是连接主体
    const IJoinRelationshipBehavior* elementJoinBehavior = pGeometryRepCpt->GetJoinRelationship();
    if (elementJoinBehavior)
    {
        // middle
        vector<ElementId> middleJoinElementIds = elementJoinBehavior->GetElementJoinIdsAtMiddle();
        FOR_EACH(middleId, middleJoinElementIds)
        {
            const IElementJoin* joinElement = dynamic_cast<const IElementJoin*>(pDoc->GetElement(middleId));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(!joinElement, L"连接对象必需最后复制",L"GDMPLab",L"2024-03-30");
        }

        // start
        vector<ElementId> startJoinElementIds = elementJoinBehavior->GetElementJoinIdsAtStart();
        FOR_EACH(startId, startJoinElementIds)
        {
            const IElementJoin* joinElement = dynamic_cast<const IElementJoin*>(pDoc->GetElement(startId));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(!joinElement, L"连接对象必需最后复制",L"GDMPLab",L"2024-03-30");
        }

        // end
        vector<ElementId> endJoinElementIds = elementJoinBehavior->GetElementJoinIdsAtEnd();
        FOR_EACH(endId, endJoinElementIds)
        {
            const IElementJoin* joinElement = dynamic_cast<const IElementJoin*>(pDoc->GetElement(endId));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(!joinElement, L"连接对象必需最后复制",L"GDMPLab",L"2024-03-30");
        }
    }

    return true;
}

bool GbmpClonedElementPostProcessor::ProcessJoinElement(IElement* pElement)
{
    IDocument* pDoc = pElement->GetDocument();
    ElementId elementId = pElement->GetElementId();

    //如果是连接对象
    const IElementJoin* joinElement = dynamic_cast<const IElementJoin*>(pElement);
    if (joinElement)
    {
        ElementId attachingId = joinElement->GetAttachingId();
        JoinPosition attachingPosition = joinElement->GetAttachingPosition();
        if (attachingId.IsValid())
        {
            IElement* pAttaching = pDoc->GetElement(attachingId);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pAttaching, L"pAttaching为空",L"GDMPLab",L"2024-03-30");
            IGeometryRelationshipComponent* pGeometryRepCpt = pAttaching->GetGeometryRelationshipComponent();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pGeometryRepCpt, L"pGeometryRepCpt为空",L"GDMPLab",L"2024-03-30");
            IJoinRelationshipBehavior* joinBehavior = pGeometryRepCpt->GetJoinRelationship();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(joinBehavior, L"joinBehavior为空",L"GDMPLab",L"2024-03-30");
            joinBehavior->AddElementJoinId(elementId, attachingPosition);
        }

        ElementId attachedId = joinElement->GetAttachedId();
        JoinPosition attachedPosition = joinElement->GetAttachedPosition();
        if (attachedId.IsValid())
        {
            IElement* pAttached = pDoc->GetElement(attachedId);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pAttached, L"pAttached为空",L"GDMPLab",L"2024-03-30");
            IGeometryRelationshipComponent* pGeometryRepCpt = pAttached->GetGeometryRelationshipComponent();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pGeometryRepCpt, L"pGeometryRepCpt为空",L"GDMPLab",L"2024-03-30");
            IJoinRelationshipBehavior* joinBehavior = pGeometryRepCpt->GetJoinRelationship();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(joinBehavior, L"joinBehavior为空",L"GDMPLab",L"2024-03-30");
            joinBehavior->AddElementJoinId(elementId, attachedPosition);
        }
    }

    return true;
}

bool GbmpClonedElementPostProcessor::ProcessOpenedOrOpeningElement(IElement* pElement)
{
    IDocument* pDoc = pElement->GetDocument();
    ElementId elementId = pElement->GetElementId();

    //如果是被开洞对象
    IInstance* openedInstance = dynamic_cast<IInstance*>(pElement);
    if (openedInstance)
    {
        IGeometryRelationshipComponent* pGeometryRepCpt = openedInstance->GetGeometryRelationshipComponent();
        IOpeningRelationshipBehavior* openingRelationshipBehavior = pGeometryRepCpt->GetOpeningRelationship();
        if (openingRelationshipBehavior)
        {
            const vector<ElementId> openingIds = openingRelationshipBehavior->GetElementOpeningIds();
            openingRelationshipBehavior->DeleteElementOpeningIds(openingIds);
        }
    }

    return true;
}

bool GbmpClonedElementPostProcessor::ProcessOpenElement(IElement* pElement)
{
    IDocument* pDoc = pElement->GetDocument();
    ElementId elementId = pElement->GetElementId();

    //如果是连接对象
    const IElementOpening* openElement = dynamic_cast<const IElementOpening*>(pElement);
    if (openElement)
    {
        //主动打洞对象（需要调整）
        {
            ElementId openingId = openElement->GetOpeningId();

            IInstance* openingInstance = dynamic_cast<IInstance*>(pDoc->GetElement(openingId));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(openingInstance, L"openingInstance为空",L"GDMPLab",L"2024-03-30");
            IGeometryRelationshipComponent* pGeometryRepCpt = openingInstance->GetGeometryRelationshipComponent();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pGeometryRepCpt, L"pGeometryRepCpt为空",L"GDMPLab",L"2024-03-30");
            IOpeningRelationshipBehavior* openingRelationshipBehavior = pGeometryRepCpt->GetOpeningRelationship();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(openingRelationshipBehavior, L"openingRelationshipBehavior为空",L"GDMPLab",L"2024-03-30");

            //打洞关系建立
            openingRelationshipBehavior->AddElementOpeningId(openElement->GetElementId());
        }

        //被动打洞对象（需要调整）
        {
            ElementId openedId = openElement->GetOpenedId();
        
            IInstance* openedInstance = dynamic_cast<IInstance*>(pDoc->GetElement(openedId));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(openedInstance, L"openedInstance为空",L"GDMPLab",L"2024-03-30");
            IGeometryRelationshipComponent* pGeometryRepCpt = openedInstance->GetGeometryRelationshipComponent();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pGeometryRepCpt, L"pGeometryRepCpt为空",L"GDMPLab",L"2024-03-30");
            IOpeningRelationshipBehavior* openingRelationshipBehavior = pGeometryRepCpt->GetOpeningRelationship();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(openingRelationshipBehavior, L"openingRelationshipBehavior为空",L"GDMPLab",L"2024-03-30");

            //打洞关系建立
            openingRelationshipBehavior->AddElementOpeningId(openElement->GetElementId());
        }
    }

    return true;
}
